#include <iostream>
#include <string>
#include <cstring>
using std::cout;
using std::endl;
using std::string;
using std::ostream;
using std::cerr;
class CowString{
private:
    char* _pstr;
    /* int need 4B */
    static const int kRefCntLength = 4;
    class CharProxy{
    private:
        CowString& _self;
        int _idx;
    public:
        CharProxy(CowString &self, int idx)
        : _self(self), _idx(idx){
        }

        /**
         * 重载强转char，可以免去写重载输出流
         * @return
         */
        operator char(){
            printf("类型转换函数被调用\n");
            return _self._pstr[_idx];
        }

        char operator=(char ch);
//         删除重载输出流
//        friend ostream& operator<<(ostream& os, const CharProxy& rhs);
    };

public:
    CowString();
    CowString(const char* pstr);
    CowString(const CowString& rhs);
    CowString& operator=(const CowString& rhs);
    ~CowString();

    friend ostream& operator<<(ostream& os, const CowString& rhs);
//     删除重载输出流
//    friend ostream& operator<<(ostream& os, const CharProxy& rhs);

    int size() const{
        return strlen(_pstr);
    }
    const char* c_str() const{
        return _pstr;
    }

    int useCount(){
        return *(int*)(_pstr - kRefCntLength);
    }

    CowString::CharProxy operator[](int index);

private:
    void initRefCnt(){
        *(int*)(_pstr - kRefCntLength) = 1;
    }
    void increaseRefCnt(){
        (*(int*)(_pstr - kRefCntLength))++;
    }
    void decreaseRefCnt(){
        (*(int*)(_pstr - kRefCntLength))--;
    }
    char* malloc_fake(const char* pstr = nullptr){
        if(pstr){
            return new char[strlen(pstr) + 1 + kRefCntLength] + kRefCntLength;
        }
        return new char[1 + kRefCntLength] + kRefCntLength;
    }

    void release(){
        decreaseRefCnt();
        if(useCount() == 0){
            delete [] (_pstr - kRefCntLength);
            _pstr = nullptr;
            cout << "release" << endl;
        }
    }
};

/**
 * 重载输出流
 * @param os
 * @param rhs
 * @return
 */
ostream& operator<<(ostream& os, const CowString& rhs){
    os << rhs._pstr;
    return os;
}


/**
 * 无参构造
 */
CowString::CowString(){
    /**
     * 4B存放引用计数
     * 1B存放null
     */
    _pstr = malloc_fake();
    initRefCnt();
    cout << "constructor" << endl;
}


/**
 * 析构
 */
CowString::~CowString(){
    release();
}

/**
 * 拷贝构造
 * @param rhs
 */
CowString::CowString(const CowString& rhs) {
    /* 浅拷贝 */
    _pstr = rhs._pstr;
    increaseRefCnt();
    cout << "copy constructor" << endl;
}

/**
 * c风格有参构造
 * @param pstr
 */
CowString::CowString(const char *pstr):_pstr(malloc_fake(pstr)) {
    initRefCnt();
    strcpy(_pstr, pstr);
    cout << "char* constructor" << endl;
}

/**
 * 重载赋值运算符
 * @param rhs
 * @return
 */
CowString& CowString::operator=(const CowString& rhs){
    if (this != &rhs){  /* 自赋值 */
        release();  /* 尝试回收 */
        _pstr = rhs._pstr;   /* 浅拷贝 */
        increaseRefCnt();   /* 引用计数加一 */
    }
    return *this;
}

/**
 * CharProxy 对象保存一个下标和一个引用向上绑定str1
 * @param index
 * @return
 */
CowString::CharProxy CowString::operator[](int index){
    return CharProxy(*this, index);
}

char CowString::CharProxy::operator=(char ch) {
    if(_idx >= 0 && _idx < _self.size()){
        if(_self.useCount() > 1){
            /* 原来的引用计数-1*/
            _self.decreaseRefCnt();
            /* 深拷贝 */
            char* ptemp = _self.malloc_fake(_self._pstr);
            strcpy(ptemp, _self._pstr);
            /* 修改指向 */
            _self._pstr = ptemp;
            /* 新的空间，初始化引用计数 */
            _self.initRefCnt();
        }

        /* 执行写操作 */
        _self._pstr[_idx] = ch;
        return _self._pstr[_idx];
    }
    cerr << "out of range" << endl;
    /**
     * 返回引用时必须要加static
     */
    static char nullchar = '\0';
    return nullchar;
}

// 删除重载输出流
//ostream& operator<<(ostream& os, const CowString::CharProxy & rhs){
//    if(rhs._idx >= 0 && rhs._idx < rhs._self.size()){
//        os << rhs._self._pstr[rhs._idx];
//    }else{
//        os << "out of range" << endl;
//    }
//    return os;
//}

// 补充:输出流运算符自带转换字符串效果，所以自带强转效果
/*
 * template <class _Traits>inline basic_ostream<char, _Traits>&
 * operator<<(basic_ostream<char, _Traits>& __out, char __c){
 *     return __ostream_insert(__out, &__c, 1);
 * }
 *
 */
void test1(){
    CowString string1("hello");
    string1[0] = 'H';
    printf("%p\n", string1[0]);
    printf("%c\n", (char)string1[0]);
    cout << string1[0] << endl;
    cout << string1[0].operator char() << endl;
    cout << (char)string1[0] << endl;
}

int main() {
    test1();
    return 0;
}